package com.test.lock.synAndReentrantLock;

import java.util.concurrent.locks.*;

/**
 * synchronized与lock之间的区别
 * 题目：多线程之间按顺序调用，实现A->B->C
 * AA打印1次，BB打印2次，CC打印3次
 * 紧接着
 * AA打印1次，BB打印2次，CC打印3次
 * 。。。
 * 来3轮
 *
 * @author wangjie
 * @version V1.0
 * @date 2019/12/24
 */
public class SynAndReentrantLockDemo {

    public static void main(String[] args) {

        ShareResource shareResource = new ShareResource();

        new Thread(() ->{

            for(int i =0;i < 3;i++){
                shareResource.print();
            }

        },"AA").start();

        new Thread(() ->{

            for(int i =0;i < 3;i++){
                shareResource.print2();
            }

        },"BB").start();

        new Thread(() ->{

            for(int i =0;i < 3;i++){

                shareResource.print3();
            }

        },"CC").start();


    }
}

/**
 * 资源类
 */
class ShareResource{

    /**
     *   A:1,B:2,C:3
     */
    private int num = 1;

    private Lock lock = new ReentrantLock();
    private Condition c1 = lock.newCondition();
    private Condition c2 = lock.newCondition();
    private Condition c3 = lock.newCondition();

    public void print(){
        lock.lock();
        try {

            while (1 != num){
                c1.await();
            }

            System.out.println(Thread.currentThread().getName() + "\t" + 1);


            num = 2;
            c2.signal();

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void print2(){
        lock.lock();
        try {

            while (2 != num){
                c2.await();
            }
            for (int i = 0;i<2;i++){
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }

            num = 3;
            c3.signal();

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void print3(){
        lock.lock();
        try {

            while (3 != num){
                c3.await();
            }
            for (int i = 0;i<3;i++){
                System.out.println(Thread.currentThread().getName() + "\t" + i);
            }

            num = 1;
            c1.signal();

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}
